﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;

namespace LINQtoQIF
{
    internal class QifStream
    {
        private StreamReader _inStream;

        public QifStream(StreamReader inStream)
        {
            this._inStream = inStream;
            // TODO: create writing possibility
        }

        public bool ReadTransactions<T>(ref List<T> transactions) where T : IQifTransaction
        {
            // Go to start
            _inStream.BaseStream.Position = 0;

            // Read header line
            var header = _inStream.ReadLine();

            // Get transaction type
            var transactionType = string.Empty;
            if (header.StartsWith("!Type:"))
            {
                transactionType = header.Substring(6).ToUpper();
            }
            else
            {
                throw new FormatException("Invalid Header format;");
            }

            // Go to start
            _inStream.BaseStream.Position = 1;


            // dummy proof
            if (transactions == null)
            {
                transactions = new List<T>();
            }

            // Use convention to find the mapper
            var mapperName = typeof(T).Name + "Map";
            var mapperClass = (from a in AppDomain.CurrentDomain.GetAssemblies()
                             from t in a.GetTypes()
                               where t.Namespace == "LINQtoQIF" && t.Name == mapperName
                             select t).FirstOrDefault();

            if (mapperClass == null)
                throw new NotImplementedException("The class '" + mapperName + "' was not found.");

            var mapper = (TransactionMap<T>)Activator.CreateInstance(mapperClass);

            // Get the next transaction
            string line = string.Empty;
            while(_inStream.BaseStream.Position < _inStream.BaseStream.Length - 1)
            {
                var transaction = (T)Activator.CreateInstance(typeof(T));
                string transactionstring = string.Empty;
                while (!(line = _inStream.ReadLine()).StartsWith("^"))
                {
                    transactionstring += line + Environment.NewLine;
                }
                // Parse, map and add to list
                transaction = mapper.Parse<T>(transactionstring);
                transaction.Type = transactionType;
                transactions.Add((T)Convert.ChangeType(transaction,typeof(T)));
            }
            return true;
        }


    }
}
